home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 2002 November / SGI Freeware 2002 November - Disc 3.iso / dist / fw_qt3.idb / usr / freeware / Qt / examples / tetrix / qdragapp.cpp.z / qdragapp.cpp
C/C++ Source or Header  |  2002-04-08  |  11KB  |  503 lines

  1. /****************************************************************************
  2. ** $Id:  qt/qdragapp.cpp   3.0.3   edited Mar 12 19:00 $
  3. **
  4. ** Copyright (C) 1992-2000 Trolltech AS.  All rights reserved.
  5. **
  6. ** This file is part of an example program for Qt.  This example
  7. ** program may be used, distributed and modified without limitation.
  8. **
  9. *****************************************************************************/
  10.  
  11. #include "qdragapp.h"
  12. #include "qptrlist.h"
  13. #include "qintdict.h"
  14. #include "qpopupmenu.h"
  15. #include "qcolor.h"
  16. #include "qwidget.h"
  17. #include "qfontmetrics.h"
  18. #include "qcursor.h"
  19. #include "qobjectlist.h"
  20.  
  21. QWidget *cursorWidget( QPoint * = 0 );
  22.  
  23. class QDragger;
  24.  
  25.  
  26. class DropWindow : public QWidget
  27. {
  28.     Q_OBJECT
  29. public:
  30.     void paintEvent( QPaintEvent * );
  31.     void closeEvent( QCloseEvent * );
  32.  
  33.     QDragger *master;
  34. };
  35.  
  36.  
  37. struct DropInfo {
  38.     DropInfo()    { w=0; }
  39.    ~DropInfo()  { delete w; }
  40.     DropWindow *w;
  41.     bool userOpened;
  42. };
  43.  
  44. struct DraggedInfo {
  45.     QWidget *w;
  46.     QWidget *mother;
  47.     QPoint   pos;
  48. };
  49.  
  50.  
  51. class QDragger : public QObject
  52. {
  53.     Q_OBJECT
  54. public:
  55.     QDragger();
  56.     ~QDragger();
  57.  
  58.     bool notify( QObject *, QEvent * ); // event filter
  59.     void closeDropWindow( DropWindow * );
  60. public slots:
  61.     void openDropWindow();
  62.     void killDropWindow();
  63.     void killAllDropWindows();
  64.     void sendChildHome();
  65.     void sendAllChildrenHome();
  66. private:
  67.     bool isParentToDragged( QWidget * );
  68.     bool noWidgets( QWidget * );
  69.     void killDropWindow( DropInfo * );
  70.     void killAllDropWindows( bool );
  71.     void sendChildHome( DraggedInfo * );
  72.     void sendAllChildrenHome( QWidget * );
  73.     QWidget *openDropWindow( const QRect&, bool );
  74.  
  75.     bool startGrab();
  76.     void grabFinished();
  77.     bool dragEvent( QWidget *, QMouseEvent * );
  78.     bool killDropEvent( QMouseEvent * );
  79.     bool sendChildEvent( QMouseEvent * );
  80.  
  81.     bool           killingDrop;
  82.     bool           sendingChild;
  83.     QWidget          *clickedWidget;
  84.     QWidget          *hostWidget;
  85.     QCursor           cursor;
  86.  
  87.     QPopupMenu*           menu;
  88.     QPoint           clickOffset;
  89.     QColor           dragBackground;
  90.     QColor           dragForeground;
  91.     DraggedInfo           dragInfo;
  92.     QIntDict<DraggedInfo>  draggedDict;
  93.     QIntDict<DropInfo>       dropDict;
  94. };
  95.  
  96.  
  97. QDragApplication::QDragApplication( int &argc, char **argv )
  98.     : QApplication( argc, argv )
  99. {
  100.     dragger = new QDragger;
  101. }
  102.  
  103. QDragApplication::~QDragApplication()
  104. {
  105.     delete dragger;
  106. }
  107.  
  108. bool QDragApplication::notify( QObject *o, QEvent *e )
  109. {
  110.     if ( dragger && !dragger->notify( o, e ) )
  111.     return o->event( e );
  112.     else
  113.     return FALSE;
  114. }
  115.  
  116. void DropWindow::paintEvent( QPaintEvent * )
  117. {
  118.     const char *msg    = "Drag widgets and drop them here or anywhere!";
  119.     int        startX = ( width() - fontMetrics().width( msg ) )/2;
  120.     startX           = startX < 0 ? 0 : startX;
  121.  
  122.     drawText( startX, height()/2, msg );
  123. }
  124.  
  125. void DropWindow::closeEvent( QCloseEvent *e )
  126. {
  127.     master->closeDropWindow( this );
  128.     e->ignore();
  129. }
  130.  
  131. QDragger::QDragger()
  132. {
  133.     dragInfo.w     = 0;
  134.     hostWidget     = 0;
  135.     killingDrop     = FALSE;
  136.     sendingChild = FALSE;
  137.     draggedDict.setAutoDelete( TRUE );
  138.     dropDict   .setAutoDelete( TRUE );
  139.  
  140.     menu = new QPopupMenu;
  141.     menu->insertItem( "Open drop window", 1 );
  142.     menu->insertItem( "Kill drop window", 2 );
  143.     menu->insertItem( "Kill all drop windows", 3 );
  144.     menu->insertSeparator();
  145. //    menu->insertItem( "Send child home", 4 );
  146.     menu->insertItem( "Send all children home", 5 );
  147.  
  148.     menu->connectItem( 1, this, SLOT(openDropWindow()) );
  149.     menu->connectItem( 2, this, SLOT(killDropWindow()) );
  150.     menu->connectItem( 3, this, SLOT(killAllDropWindows()) );
  151. //    menu->connectItem( 4, this, SLOT(sendChildHome()) );
  152.     menu->connectItem( 5, this, SLOT(sendAllChildrenHome()) );
  153. }
  154.  
  155. QDragger::~QDragger()
  156. {
  157.     delete menu;
  158. }
  159.  
  160.  
  161. bool QDragger::notify( QObject *o, QEvent *e )
  162. {
  163.     if ( !o->isWidgetType() || o == menu )
  164.     return FALSE;
  165.     switch( e->type() ) {
  166.     case QEvent::MouseMove:
  167.          {
  168.          QMouseEvent *tmp = (QMouseEvent*) e;
  169.          if ( killingDrop )
  170.              return killDropEvent( tmp );
  171.          if ( sendingChild )
  172.              return sendChildEvent( tmp );
  173.          if ( tmp->state() & QMouseEvent::RightButton )
  174.              return dragEvent( (QWidget*) o, tmp );
  175.          break;
  176.          }
  177.     case QEvent::MouseButtonPress:
  178.     case QEvent::MouseButtonRelease:
  179.     case QEvent::MouseButtonDblClick:
  180.          {
  181.          QMouseEvent *tmp = (QMouseEvent*) e;
  182.          if ( killingDrop )
  183.              return killDropEvent( tmp );
  184.          if ( sendingChild )
  185.              return sendChildEvent( tmp );
  186.          if ( tmp->button() == QMouseEvent::RightButton )
  187.              return dragEvent( (QWidget*) o, tmp );
  188.          }
  189.          break;
  190.     default:
  191.          break;
  192.     }
  193.     return FALSE;
  194. }
  195.  
  196. bool QDragger::isParentToDragged( QWidget *w )
  197. {
  198.     QIntDictIterator<DraggedInfo> iter( draggedDict );
  199.  
  200.     DraggedInfo *tmp;
  201.     while( (tmp = iter.current()) ) {
  202.     ++iter;
  203.     if ( tmp->mother == w )
  204.         return TRUE;
  205.     }
  206.     return FALSE;
  207. }
  208.  
  209. bool QDragger::noWidgets( QWidget *w )
  210. {
  211.     const QObjectList *l = w->children();
  212.     if ( !l )
  213.     return TRUE;
  214.     QObjectListIt iter( *l );
  215.     QObject *tmp;
  216.     while( (tmp = iter.current()) ) {
  217.     ++iter;
  218.     if ( tmp->isWidgetType() )
  219.         return FALSE;
  220.     }
  221.     return TRUE;
  222. }
  223.  
  224. void QDragger::sendAllChildrenHome( QWidget *w )
  225. {
  226.     const QObjectList *l = w->children();
  227.     if ( !l )
  228.     return;
  229.     QObjectListIt iter( *l );
  230.     QObject *tmp;
  231.     while( (tmp = iter.current()) ) {
  232.     ++iter;
  233.     if ( tmp->isWidgetType() ) {
  234.         sendAllChildrenHome( (QWidget*) tmp );
  235.         DraggedInfo *di = draggedDict.find( (long) tmp );
  236.         if ( di )
  237.         sendChildHome( di );
  238.     }
  239.     }
  240. }
  241.  
  242. bool QDragger::dragEvent( QWidget *w, QMouseEvent *e )
  243. {
  244.     switch( e->type() ) {
  245.     case QEvent::MouseButtonDblClick:
  246.     case QEvent::MouseButtonPress: {
  247.         if ( !noWidgets( w ) || // has widget children
  248.          isParentToDragged( w )    || // has had widget children
  249.          w->parentWidget() == 0 ) {       // is top level window
  250.         hostWidget = w;
  251.         menu->popup( w->mapToGlobal( e->pos() ) );
  252.         return TRUE;
  253.         }
  254.         if ( !draggedDict.find( (long) w ) ) {
  255.         DraggedInfo *tmp = new DraggedInfo;
  256.         tmp->w          = w;
  257.         tmp->mother      = w->parentWidget();
  258.         tmp->pos          = w->frameGeometry().topLeft();
  259.         draggedDict.insert( (long) w, tmp );
  260.         }
  261.         dragBackground     = w->backgroundColor();
  262.         dragForeground     = w->foregroundColor();
  263.         dragInfo.w     = w;
  264.         dragInfo.mother = w->parentWidget();
  265.         dragInfo.pos     = w->frameGeometry().topLeft();
  266.         clickOffset = e->pos();
  267.         dragInfo.w  = w;
  268.         QPoint p    = w->mapToGlobal(QPoint(0,0));
  269.         w->reparent( 0, WType_Popup, p, TRUE );
  270.  
  271.         return TRUE;
  272.     }
  273.     case QEvent::MouseButtonRelease:
  274.     case QEvent::MouseMove: {
  275.         if ( dragInfo.w != 0 ) {
  276.         QPoint p = QCursor::pos() - clickOffset;
  277.         dragInfo.w->move( p );
  278.         if ( e->type() == QEvent::MouseMove )
  279.             return TRUE;
  280.         } else {
  281.         return FALSE;
  282.         }
  283.         if ( !dragInfo.w )
  284.         return FALSE;
  285.         if ( w != dragInfo.w )
  286.         w = dragInfo.w;
  287.         dragInfo.w = 0;
  288.         w->hide();
  289.         QPoint pos;
  290.         QWidget *target = cursorWidget( &pos );
  291.         pos = pos - clickOffset;
  292.         QPoint p;
  293.         if ( !target ) {
  294.         target = openDropWindow( QRect( pos, w->size() ),
  295.                      FALSE);
  296.         p = QPoint( 0, 0 );
  297.         }
  298.         else
  299.         p = target->mapFromGlobal( pos );
  300.         w->reparent( target, 0, p, TRUE );
  301.         DropInfo *tmp = dropDict.find( (long) dragInfo.mother );
  302.         if ( tmp ) {
  303.         if ( !tmp->userOpened && noWidgets( tmp->w ) )
  304.             dropDict.remove( (long) tmp->w );
  305.         }
  306.         if ( !target->isVisible() )
  307.         target->show();
  308.       }
  309.       return TRUE;
  310.     default:
  311.       return FALSE;
  312.     }
  313. }
  314.  
  315. bool QDragger::killDropEvent( QMouseEvent *e )
  316. {
  317.     switch( e->type() ) {
  318.     case QEvent::MouseButtonDblClick:
  319.     case QEvent::MouseButtonPress:
  320.         clickedWidget = cursorWidget();
  321.         return TRUE;
  322.     case QEvent::MouseButtonRelease:
  323.         hostWidget->releaseMouse();
  324.         if ( clickedWidget ) {
  325.         DropInfo *tmp = dropDict.find( (long) clickedWidget );
  326.         if( tmp ) {
  327.             killDropWindow( tmp );
  328.             dropDict.remove( (long) tmp->w );
  329.         }
  330.         }
  331.         grabFinished();
  332.         return TRUE;
  333.     case QEvent::MouseMove:
  334.         return TRUE;
  335.     default:
  336.         break;
  337.     }
  338.     return FALSE;
  339. }
  340.  
  341. bool QDragger::sendChildEvent( QMouseEvent *e )
  342. {
  343.     switch( e->type() ) {
  344.     case QEvent::MouseButtonDblClick:
  345.     case QEvent::MouseButtonPress:
  346.         clickedWidget = cursorWidget();
  347.         return TRUE;
  348.     case QEvent::MouseButtonRelease:
  349.         hostWidget->releaseMouse();
  350.         if ( clickedWidget ) {
  351.         DraggedInfo *tmp = draggedDict.find((long) clickedWidget);
  352.         if( tmp ) {
  353.             QWidget *parent = tmp->w->parentWidget();
  354.             sendChildHome( tmp );
  355.             DropInfo *dri = dropDict.find( (long) parent );
  356.             if ( dri && noWidgets(dri->w) && !dri->userOpened ) {
  357.             killDropWindow( dri );
  358.             dropDict.remove( (long) dri );
  359.             }
  360.         }
  361.         grabFinished();
  362.         }
  363.         return TRUE;
  364.     case QEvent::MouseMove:
  365.         return TRUE;
  366.     default:
  367.         break;
  368.     }
  369.     return FALSE;
  370. }
  371.  
  372. bool QDragger::startGrab()
  373. {
  374.     if ( !hostWidget )
  375.     return FALSE;
  376.     clickedWidget = 0;
  377.     cursor      = hostWidget->cursor();
  378.     hostWidget->grabMouse();
  379.     hostWidget->setCursor( QCursor( CrossCursor ) );
  380.     return TRUE;
  381. }
  382.  
  383. void QDragger::grabFinished()
  384. {
  385.     killingDrop     = FALSE;
  386.     sendingChild = FALSE;
  387.     hostWidget->setCursor( cursor );
  388. }
  389.  
  390. void QDragger::closeDropWindow( DropWindow *w )
  391. {
  392.     DropInfo *tmp = dropDict.find( (long) w);
  393.     if( tmp )
  394.     killDropWindow( tmp );
  395. }
  396.  
  397. void QDragger::openDropWindow()
  398. {
  399.     QWidget *tmp = openDropWindow( QRect(100, 100, 300, 200), TRUE );
  400.     tmp->show();
  401. }
  402.  
  403. QWidget *QDragger::openDropWindow( const QRect &r, bool user )
  404. {
  405.     DropInfo *tmp = new DropInfo;
  406.     DropWindow *w = new DropWindow;
  407.     if ( user ) {
  408.     tmp->userOpened = TRUE;
  409.     w->setCaption( "Drop window" );
  410.     } else {
  411.     tmp->userOpened = FALSE;
  412.     w->setCaption( "Auto drop window" );
  413.     }
  414.     tmp->w = w;
  415.     w->master = this;
  416.     w->setGeometry( r );
  417.     dropDict.insert( (long) w, tmp );
  418.     w->show();
  419.     return w;
  420. }
  421.  
  422. void QDragger::killDropWindow()
  423. {
  424.     if ( startGrab() )
  425.     killingDrop   = TRUE;
  426. }
  427.  
  428. void QDragger::killDropWindow( DropInfo *di )
  429. {
  430.     const QObjectList *l = di->w->children();
  431.     if ( !l )
  432.     return;
  433.     QObjectListIt iter( *l );
  434.     QObject *tmp;
  435.     while( (tmp = iter.current()) ) {
  436.     ++iter;
  437.     if ( tmp->isWidgetType() ) {
  438.         DraggedInfo *dri = draggedDict.find( (long) tmp );
  439.         if ( dri ) {
  440.         sendChildHome( dri );
  441.         draggedDict.remove( (long) tmp );
  442.         }
  443.     }
  444.     }
  445.     di->w->hide();
  446. }
  447.  
  448. void QDragger::killAllDropWindows()
  449. {
  450.     killAllDropWindows( FALSE );
  451. }
  452.  
  453. void QDragger::killAllDropWindows( bool autoOnly )
  454. {
  455.     QIntDictIterator<DropInfo> iter( dropDict );
  456.  
  457.     DropInfo *tmp;
  458.     while( (tmp = iter.current()) ) {
  459.     ++iter;
  460.     if( !autoOnly || !tmp->userOpened ) {
  461.         killDropWindow( tmp );
  462.         dropDict.remove( (long) tmp->w );
  463.     }
  464.     }
  465. }
  466.  
  467. void QDragger::sendChildHome( DraggedInfo *i )
  468. {
  469.     i->w->reparent( i->mother, 0, i->pos, TRUE );
  470. }
  471.  
  472. void QDragger::sendChildHome()
  473. {
  474.     if ( startGrab() )
  475.     sendingChild  = TRUE;
  476. }
  477.  
  478. void QDragger::sendAllChildrenHome()
  479. {
  480.     QIntDictIterator<DraggedInfo> iter( draggedDict );
  481.  
  482.     DraggedInfo *tmp;
  483.     while( (tmp = iter.current()) ) {
  484.     ++iter;
  485.     sendChildHome( tmp );
  486.     draggedDict.remove( (long) tmp->w );
  487.     }
  488.     killAllDropWindows( TRUE );
  489.     draggedDict.clear();
  490. }
  491.  
  492.  
  493. QWidget *cursorWidget( QPoint *p )
  494. {
  495.     QPoint curpos = QCursor::pos();
  496.     if ( p )
  497.     *p = curpos;
  498.     return QApplication::widgetAt( curpos );
  499. }
  500.  
  501.  
  502. #include "qdragapp.moc"
  503.